#ifndef BLACKBOARDMANAGER_H
#define BLACKBOARDMANAGER_H

#include "NodeList.h"
#include "DrawPath.h"
#include "network/ConnectionManager.h"
#include "network/packet/Packets.h"

#include <QPoint>
#include <QTimer>
#include <QColor>

class BlackboardState;
class MainWindow;

class BlackboardManager : public QObject
{
   Q_OBJECT
public:
    BlackboardManager();
    virtual ~BlackboardManager();

    /**
      * Initializes new network.
      **/
    void initNew(const QString & address, quint16 port, QColor penColor, int width, int height);

    /**
      * Join to specific node.
      **/
    void joinSpecific(const QString & listenAddres, quint16 listenPort, QColor penColor,
                      const QString & joinAddress, quint16 joinPort);

    NodeList * getNodeListModel() { return nodeList; }
    void sendPacket(AbstractPacket * packet);

    const Node & getThisNode() const { return nodeList->getThisNode(); }
    const Node & getPrevNode() const { return nodeList->getNextNode(); }
    const Node & getNextNode() const { return nodeList->getPrevNode(); }

    void setSize(int width, int height);

    int getWidth() const { return width; }
    int getHeight() const { return height; }

    void processAndSendPaintPacket(PaintPacket * paintPacket);
    void processMutualExclusionTokenPacket(MutualExclusionTokenPacket *packet);

    void initPainting();

    void switchState(BlackboardState *nextState);

    const QImage & getCurrentBlackboardImage();
    void resetImage(const QImage & image);

    void requestLock();
    void requestUnlock();
public slots:
    void packetReceived(AbstractPacket *);
    void connectionClosed(const QString & address, quint16 port);

    void pointDrawed(QPoint point);

    void paintTimerEvent();
    void checkNodesStatus();
    void checkMutualExclusion();
    void sendMutualExclusionToken();

signals:
    void sizeChanged(int, int);
    void pathsReceived(const QList<DrawPath *> *, QColor);
    void imageReceived(const QImage &);
    void lockPaintChanged(bool value);

protected:
    QList<DrawPath *> * getCurrentDrawPaths();

private:
    BlackboardState * blackboardState;
    ConnectionManager connection;
    NodeList *nodeList;
    QList<DrawPath *> userDrawPaths;
    DrawPath * currentDrawPath;

    int width, height;

    bool hasMutualLock;
    bool requestMutualLock, requestMutualUnlock;
    QTime lastMutualExclusionTokenReceivedTime;
    QTime mutalExclusionStartTime;
    MutualExclusionToken mutualExclusionToken;

    QTimer *paintTimer, *nodeStatusCheckTimer, *mutualExclusionCheckTimer;
    QImage *blackboardImage;
};

#endif // BLACKBOARDMANAGER_H
